package com.bea.ftd.dashboard.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bea.ftd.common.ValidationException;
import com.bea.ftd.common.dao.ApiDefineRepo;
import com.bea.ftd.common.dao.MsgOutConfRepo;
import com.bea.ftd.common.dao.PartnerInfoRepo;
import com.bea.ftd.common.entity.ApiDefine;
import com.bea.ftd.common.entity.MsgOutConf;
import com.bea.ftd.common.entity.PartnerInfo;
import com.bea.ftd.common.enums.ValidationErrorCode;
import com.bea.ftd.common.utils.XmlUtils;
import com.bea.ftd.dashboard.service.IGatewayService;
import com.bea.ftd.dashboard.service.IMsgOutConfService;
import com.bea.ftd.dashboard.validator.BooleanValidator;
import com.bea.ftd.dashboard.validator.CustomTypeValidator;
import com.bea.ftd.dashboard.validator.NumberValidator;
import com.bea.ftd.dashboard.validator.StringValidator;
import com.google.gson.Gson;

@Service
public class MsgOutConfServiceImpl implements IMsgOutConfService, IGatewayService {
	private Logger LOGGER = LoggerFactory.getLogger(MsgOutConfServiceImpl.class);

	@Autowired
	private NumberValidator numberValidator;
	@Autowired
	private StringValidator stringValidator;
	@Autowired
	private BooleanValidator booleanValidator;
	@Autowired
	private CustomTypeValidator customTypeValidator;
	
	@Autowired
	private MsgOutConfRepo msgOutConfRepo;
	@Autowired
	private ApiDefineRepo apiDefineRepo;
	@Autowired
	private PartnerInfoRepo partnerInfoRepo;

	@Override
	public void addMsgOutConf(MsgOutConf msgOutConf) throws ValidationException {
		validateInputParams(msgOutConf);
		setCreateOrUpdateTime(msgOutConf, msgOutConfRepo);
		msgOutConfRepo.save(msgOutConf);
	}
	
	/**
	 * 验证输入参数是否有效
	 * 
	 * @param msgMapping
	 * @throws ValidationException
	 */
	private void validateInputParams(MsgOutConf msgOutConf) throws ValidationException {
		
//		if (!numberValidator.isNonNegtiveNumber(msgOutConf.getApiId())) {
//			throw new ValidationException(ValidationErrorCode.EMPTY_VALUE, "API ID必须为大于等于0的值");
//		}

		if (stringValidator.isEmptyString(msgOutConf.getParamName())) {
			throw new ValidationException(ValidationErrorCode.EMPTY_VALUE, "参数名不能为空");
		}

		if (stringValidator.isEmptyString(msgOutConf.getParamNote())) {
			throw new ValidationException(ValidationErrorCode.EMPTY_VALUE, "参数注释不能为空");
		}

		if (!customTypeValidator.isValidParamType(msgOutConf.getParamType())) {
			throw new ValidationException(ValidationErrorCode.INVALID_TYPE, "无效的参数类型");
		}

		if (!numberValidator.isNonNegtiveNumber(msgOutConf.getParamLength())) {
			throw new ValidationException(ValidationErrorCode.INVALID_NUMBER, "参数长度必须为大于等于0的值");
		}

		if (!booleanValidator.isBooleanType(msgOutConf.getIsActivated())) {
			throw new ValidationException(ValidationErrorCode.EMPTY_VALUE, "无效的isActivated值");
		}

		if (!booleanValidator.isBooleanType(msgOutConf.getIsEmpty())) {
			throw new ValidationException(ValidationErrorCode.EMPTY_VALUE, "无效的isEmpty值");
		}

		if (!customTypeValidator.isValidEncryptStrategy(msgOutConf.getEncryptStrategy())) {
			throw new ValidationException(ValidationErrorCode.EMPTY_VALUE, "无效的加密策略");
		}
		
	}

	@Override
	public List<MsgOutConf> getAllMsgOutConfs() {
		try {
			return msgOutConfRepo.findAll();
		} catch (Exception e) {
			LOGGER.error("error when querying msgOutConf from database " + e.getMessage());
			return null;
		}
	}

	@Transactional
	@Override
	public void addMsgInConfFromExample(String apiId, String exampleData) throws Exception{
		ApiDefine apiDefine = apiDefineRepo.findById(apiId).get();
		String partnerCode = apiDefine.getParnterCode();
		PartnerInfo partnerInfo = partnerInfoRepo.findByPartnerCode(partnerCode);
		String dataType = partnerInfo.getMsgInType();
		msgOutConfRepo.deleteMsgOutByApiId(apiId);
		if (dataType.equalsIgnoreCase("xml")) {
			Map<String, Object> map = XmlUtils.Xml2Map(exampleData);
			saveMsgOutConf(map, apiId,"");

		} else if (dataType.equalsIgnoreCase("json")) {
			Gson gson = new Gson();
			Map<String, Object> map = gson.fromJson(exampleData, Map.class);
			saveMsgOutConf(map, apiId,"");
		}
		
	}
	
	private void saveMsgOutConf(Map<String, Object> map, String api_id,String parent) throws Exception {

		int size = map.keySet().size();
		List<String> keylist = new ArrayList<>();

		for (String key : map.keySet()) {
			String type = map.get(key).getClass().getName();
			MsgOutConf msgOutConf = new MsgOutConf();
			msgOutConf.setApiId(api_id);
			msgOutConf.setParamName(key);
			msgOutConf.setEncryptStrategy((long) 0);
			msgOutConf.setParamLength((long) 255);
			msgOutConf.setIsActivated((long) 1);
			msgOutConf.setCreateTime(new Date());
			msgOutConf.setParamType(type);
			msgOutConf.setIsEmpty((long) 0);
			msgOutConf.setUpdateTime(new Date());
			msgOutConf.setParamNote("");
			msgOutConf.setParentNode(parent);
			msgOutConfRepo.save(msgOutConf);


			if(type.equals("java.util.LinkedHashMap")){
				size--;
				keylist.add(key);
			}else{
				size--;
			}

		}
		if(size == 0){
			for(String keyone:keylist){
				parent = keyone;
				saveMsgOutConf((Map)map.get(keyone),api_id,parent);
			}

		}
	}

	@Transactional
	@Override
	public void deleteMsgOutConfContent(String apiId) {
		msgOutConfRepo.deleteMsgOutByApiId(apiId);
	}
}
